Skip to main content

PostMessages Guide

Listen for real-time iFrame events to track payment form lifecycle, field validation, and transaction results — and optionally trigger form submission from your parent page.

Before You Begin

RequirementDetails
Payment iFrameAn embedded Connected Payments payment iFrame already set up on your page
HTTPSParent page served over HTTPS
JavaScriptBasic event handling knowledge
Important

PostMessages are client-side only and depend on the customer's browser. Always use server-to-server notifications as the authoritative source for payment results.

Code samples: Code samples within this document are provided for reference purposes only and are not intended for production use.

How It Works

  1. Customer loads your page containing the Connected Payments payment iFrame
  2. The iFrame emits PostMessages as state changes (form loaded, field touched, submitted)
  3. Your message event listener receives and routes each event
  4. You respond in the UI (show spinner, resize iFrame, enable submit button)
  5. Payment outcome arrives — verify result server-side via notifications

Quick Start

Register a Message Listener

Add this to your page as early as possible — before the iFrame loads.

window.addEventListener("message", receiver, false);

function receiver(event) {
if (!event.origin.includes("connectedpayments.commbank.com.au")) {
console.warn("Rejected PostMessage from:", event.origin);
return;
}

try {
const data = JSON.parse(event.data);
handlePaymentEvent(data);
} catch (error) {
console.error("Failed to parse PostMessage:", error);
}
}

Event Reference

Lifecycle Events

Events emitted as the payment form moves through its standard states.

Eventinfo ValueFieldsTrigger
Loading"The payment form is loading."merchReferenceInitial request to Connected Payments (fetching configuration)
Rendered"The payment form has rendered."merchReferenceConfiguration retrieved, payment form rendered to DOM
Submitted"The payment form was submitted"merchReference, nameUser submits the payment form

Event Summary

Eventinfo ValueDirectionKey Fields
Form loading"The payment form is loading."ReceivemerchReference
Form rendered"The payment form has rendered."ReceivemerchReference
Form submitted"The payment form was submitted"ReceivemerchReference, name
iFrame resize"resize"Receiveresize.height, resize.width
Field interaction(no info; has errors key)ReceiveisValid, formState, stateOfFields
reCAPTCHA failed"Google recaptcha failed the validation"ReceivemerchReference, name
reCAPTCHA success"Google recaptcha validation successful"ReceivemerchReference, name
Confirmation rendered"The confirmation form has rendered."ReceivemerchReference, name
Confirmation submitted"The confirmation form has been submitted."ReceivemerchReference, name
Payment outcome"Payment outcome"ReceivemerchReference, name
Hosted response"The hosted response has rendered."ReceivemerchReference, name, cardToken
Response redirect"Redirecting response back to client defined endpoint."ReceivemerchReference, name, cardToken
External submit(no info)Sendaction: "submit"

Sending Events

External Form Submission

Submit the payment form from your parent page to coordinate submission of your own form alongside the payment form.

When to use

You have a larger checkout form and want a single submit button to trigger both your form and the payment form simultaneously.

Payload:

{
"action": "submit"
}

Implementation:

function submitPaymentIframe() {
const paymentFrame = document.getElementById("paymentFrame");
paymentFrame.contentWindow.postMessage(
JSON.stringify({ action: "submit" }),
"*",
);
}

Best practice: Only call this when isValid is true. Monitor field interaction events to track form state before enabling your submit button.

let formIsValid = false;

function handleFieldInteraction(data) {
formIsValid = data.isValid;

const submitButton = document.getElementById("externalSubmitButton");
submitButton.disabled = !formIsValid;
}

document
.getElementById("externalSubmitButton")
.addEventListener("click", () => {
if (formIsValid) {
submitPaymentIframe();
}
});

Complete Example

View full implementation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Checkout</title>
</head>
<body>
<div id="loadingSpinner">Loading payment form...</div>

<iframe
id="paymentFrame"
src="YOUR_ENTERPRISESECURE_URL"
width="100%"
height="600"
frameborder="0"
>
</iframe>

<button id="externalSubmitButton" disabled>Pay Now</button>

<script>
let formIsValid = false;

window.addEventListener("message", receiver, false);

function receiver(event) {
if (!event.origin.includes("connectedpayments.commbank.com.au")) {
console.warn("Rejected PostMessage from:", event.origin);
return;
}

try {
const data = JSON.parse(event.data);
routeEvent(data);
} catch (error) {
console.error("Failed to parse PostMessage:", error, event.data);
}
}

function routeEvent(data) {
if (data.resize) {
handleResizeEvent(data);
} else if (data.errors !== undefined) {
handleFieldInteraction(data);
} else if (data.info) {
handleInfoEvent(data);
}
}

function handleInfoEvent(data) {
switch (data.info) {
case "The payment form is loading.":
document.getElementById("loadingSpinner").style.display = "block";
break;

case "The payment form has rendered.":
document.getElementById("loadingSpinner").style.display = "none";
break;

case "The payment form was submitted":
document.getElementById("externalSubmitButton").disabled = true;
document.getElementById("externalSubmitButton").textContent =
"Processing...";
break;

case "Payment outcome":
console.log("Payment outcome received for:", data.merchReference);
break;

case "The hosted response has rendered.":
console.log("Hosted response rendered, cardToken:", data.cardToken);
break;

case "Redirecting response back to client defined endpoint.":
console.log("Redirecting, cardToken:", data.cardToken);
break;

case "The confirmation form has rendered.":
console.log("Confirmation form ready");
break;

case "The confirmation form has been submitted.":
console.log("Confirmation submitted");
break;

case "Google recaptcha failed the validation":
console.warn("reCAPTCHA failed");
break;

case "Google recaptcha validation successful":
console.log("reCAPTCHA passed");
break;

default:
console.log("Unhandled info event:", data.info);
}
}

function handleResizeEvent(data) {
const iframe = document.getElementById("paymentFrame");
if ("height" in data.resize)
iframe.height = parseInt(data.resize.height);
if ("width" in data.resize) iframe.width = parseInt(data.resize.width);
}

function handleFieldInteraction(data) {
formIsValid = data.isValid;
document.getElementById("externalSubmitButton").disabled = !formIsValid;
}

document
.getElementById("externalSubmitButton")
.addEventListener("click", () => {
if (formIsValid) {
const paymentFrame = document.getElementById("paymentFrame");
paymentFrame.contentWindow.postMessage(
JSON.stringify({ action: "submit" }),
"*",
);
}
});
</script>
</body>
</html>